package org.streets.eis.ext.rbac.component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.tree.DefaultTreeModel;

import org.apache.wicket.ResourceReference;
import org.apache.wicket.markup.html.tree.BaseTree;
import org.streets.database.SQLConnection;
import org.streets.database.datadict.ColumnDefinition;
import org.streets.database.datadict.DataDict;
import org.streets.database.datadict.DictDefinition;
import org.streets.database.datadict.TableDefinition;
import org.streets.eis.EisWebSession;
import org.streets.eis.component.tree.Node;
import org.streets.eis.component.tree.TreePanel;
import org.streets.eis.entity.User;
import org.streets.eis.ext.rbac.services.RBACAuthorizer;
import org.streets.wicket.HiveWebApplication;

public class DataDictTree extends TreePanel<DictDefinition>{

	private static final long serialVersionUID = 1L;
	
	private Map<String,Node<CategoryDefinition>> categoryNodes = new HashMap<String,Node<CategoryDefinition>>();	
	
	private static class CategoryDefinition implements DictDefinition{
		private static final long serialVersionUID = 1L;
		private String category;
		
		public CategoryDefinition(String categoryName){
			this.category = categoryName; 
		}
		
		public String getAlias() {
			return category;
		}

		public String getName() {
			return "group:"+category;
		}
	}
	
	public static final DictDefinition ROOT = new CategoryDefinition("root");
	
	public DataDictTree(String id) {
		this(id,false);
	}

	public DataDictTree(String id,boolean showCheckBox){
		super(id,(DefaultTreeModel)null,showCheckBox);
		
		SQLConnection conn = HiveWebApplication.get().getRegistry().service(SQLConnection.class);
		User user = EisWebSession.get().getUser();
		RBACAuthorizer authorizer = HiveWebApplication.get().getRegistry().service(RBACAuthorizer.class);
		
		Node<DictDefinition> rootNode = new Node<DictDefinition>(ROOT);
		rootNode.setLoaded(true);
		
		DataDict dict = HiveWebApplication.get().getRegistry().service(DataDict.class);
		List<TableDefinition> tables = dict.getTableDefs();	
		for (TableDefinition table : tables) {
			generateTable(rootNode, table,conn,authorizer,user);
		}
		
		for (Node<CategoryDefinition> categoryNode : categoryNodes.values()){
			if (categoryNode.getChildCount() == 0){
				rootNode.remove(categoryNode);
			}
		}
		
		DefaultTreeModel model = new DefaultTreeModel(rootNode);
		getTree().setDefaultModelObject(model);
		getTree().setRootLess(true); 
	}

	protected void generateTable(Node<DictDefinition> rootNode,TableDefinition table,SQLConnection conn,RBACAuthorizer authorizer,User user) {		
		String category = table.getCategory();
		if (!categoryNodes.containsKey(category)){
			CategoryDefinition cd = new CategoryDefinition(category);
			Node<CategoryDefinition> cdNode = new Node<CategoryDefinition>(cd);
			cdNode.setLoaded(true);
			categoryNodes.put(category,cdNode);
			rootNode.add(cdNode);			
		}
		Node<CategoryDefinition> parentNode = categoryNodes.get(category);
		
		Node<DictDefinition> node = new Node<DictDefinition>(table);
		node.setLoaded(true);
		parentNode.add(node);
		
		List<ColumnDefinition> columns = table.getColumns();
		for (ColumnDefinition column: columns) {
			String expr = "field:"+table.getName()+"."+column.getName()+".R";
			if (!authorizer.authorized(user, expr)) continue;
			
			Node<DictDefinition> tmp = new Node<DictDefinition>(column);
			tmp.setLoaded(true);
			node.add(tmp);
		}
		
		if (node.getChildCount() == 0 ) {
			parentNode.remove(node);
		}
	}

	@Override
	protected ResourceReference getNodeIcon(Node<DictDefinition> node){
		DictDefinition def = node.getObject();
		if (def instanceof ColumnDefinition){
			return new ResourceReference(BaseTree.class, "res/item.gif");
		} else {
			if (getTree().getTreeState().isNodeExpanded(node)){
				return new ResourceReference(BaseTree.class, "res/folder-open.gif");
			}else{
				return new ResourceReference(BaseTree.class, "res/folder-closed.gif");
			}			
		}
	
	}	
	
	@Override
	protected String getNodeText(Node<DictDefinition> object){
		DictDefinition def = object.getObject();
		return def.getAlias();
	}

}
